﻿namespace MicroCloud.Entity.BatchConfiguration
{
    /// <summary>
    /// 实体与持久化对象映射的常规属性配置
    /// </summary>
    public class PropertyEntityConfiguration : IEntityBatchConfiguration
    {
        #region 方法
        /// <summary>
        /// 配置指定的<see cref="IMutableEntityType"/>
        /// </summary>
        /// <param name="modelBuilder">模型构建器</param>
        /// <param name="mutableEntityType">实体的 <see cref="IMutableEntityType"/> 类型</param>
        /// <param name="database">数据库相关信息和操作的访问 <see cref="DatabaseFacade"/> 类型</param>
        /// <param name="dbContextOptions">数据上下文配置 <see cref="DbContextOption"/> 类型</param>
        /// <param name="dbContextType">数据上下文类型</param>
        public void Configure(ModelBuilder modelBuilder, IMutableEntityType mutableEntityType, DatabaseFacade database, DbContextOption dbContextOptions, Type dbContextType)
        {
           
            // 数据库类型
            var databaseType = dbContextOptions?.DatabaseType;
            if (databaseType == null)
            {
                var databaseProviderName = database.ProviderName.ToLower();
                if (databaseProviderName.Contains("sqlserver")) { databaseType = DatabaseType.SqlServer; }
                else if (databaseProviderName.Contains("sqlite")) { databaseType = DatabaseType.Sqlite; }
                else if (databaseProviderName.Contains("mysql")) { databaseType = DatabaseType.MySql; }
                else if (databaseProviderName.Contains("postgresql")) { databaseType = DatabaseType.PostgreSql; }
                else if (databaseProviderName.Contains("oracle")) { databaseType = DatabaseType.Oracle; }
            }

            TableAttribute table = mutableEntityType.ClrType.GetAttribute<TableAttribute>();

            string tableName = mutableEntityType.GetTableName();// 表名
            string schema = mutableEntityType.GetSchema();        // 架构名

            switch (databaseType)
            {
                case DatabaseType.SqlServer:
                
                case DatabaseType.PostgreSql:
                case DatabaseType.Oracle:
                    break;
                case DatabaseType.MySql: 
                case DatabaseType.Sqlite://不支持Schema模式
                    if (!string.IsNullOrEmpty(schema))
                    {
                        tableName = $"{schema}_{tableName}";
                        schema = string.Empty;
                    }
                    break;
            }

            //配置以关系数据库为目标时实体类型映射到的视图
            var dbViewAttribute = GetDatabaseViewAttribute(mutableEntityType.ClrType);
            if (dbViewAttribute != null)
            {
                //Console.WriteLine($"配置以关系数据库为目标时实体类型映射到的视图：{entityName}");
                if (!schema.IsMissing())
                {
                    modelBuilder.Entity(mutableEntityType.ClrType).HasNoKey().ToView(tableName, schema);
                }
                else
                {
                    modelBuilder.Entity(mutableEntityType.ClrType).HasNoKey().ToView(tableName);
                }
                // 配置实体从迁移中排除，以保证当数据库不存在该对象时自动迁移为数据库表对象的问题
                modelBuilder.Entity(mutableEntityType.ClrType).HasAnnotation(RelationalAnnotationNames.IsTableExcludedFromMigrations, true);
                return;
            }

            //配置以关系数据库为目标时实体类型映射到的数据库表（默认规则）
            if (!schema.IsMissing())
            {
                modelBuilder.Entity(mutableEntityType.ClrType).ToTable(tableName, schema);
            }
            else
            {
                modelBuilder.Entity(mutableEntityType.ClrType).ToTable(tableName);
            }

        }

        #endregion

        #region 受保护的方法
        /// <summary>
        /// 从实体类型获取数据库视图特性
        /// </summary>
        /// <param name="entityType">实体类型</param>
        /// <returns></returns>
        protected virtual DatabaseViewAttribute GetDatabaseViewAttribute(Type entityType)
        {
            DatabaseViewAttribute attribute = entityType.GetAttribute<DatabaseViewAttribute>();
            return attribute;
        }

        #endregion

    }
}